#include <fermat/dio/disk_queues.h>
#include <fermat/dio/iostats.h>
#include <fermat/dio/serving_queue_1q.h>
#include <fermat/dio/serving_request.h>

#include <map>

namespace fermat {

DiskQueues::DiskQueues()
{
    // initialize stats before ourselves
    Stats::getInstance();
}

DiskQueues::~DiskQueues()
{
    // deallocate all queues
    /*
   RequestQueueMap::iterator it = _queues.begin();
   while(it != _queues.end()) {
   		it->second->stop();
        delete it->second;
   	}
   	*/
   	stop();
}

void DiskQueues::stop()
{
	RequestQueueMap::iterator it = _queues.begin();
   	while(it != _queues.end()) {
		delete it->second;
		it++;
   	}
  
	_queues.clear();
}

void DiskQueues::MakeQueue(const FileBasePtr& file) {
    int queue_id = file->get_queue_id();

    RequestQueueMap::iterator qi = _queues.find(queue_id);
    if (qi != _queues.end())
        return;

    RequestQueue  *rq = new ServingQueue1Q();
	
	dynamic_cast<ServingQueue1Q*>(rq)->start();
    _queues[queue_id] = rq;
}

void DiskQueues::AddRequest(RequestPtr& req, DiskId disk) {

    RequestQueueMap::iterator qi = _queues.find(disk);
    RequestQueue* q = NULL;
    if (qi == _queues.end()) {
        // create new request queue
        RequestQueue  *rq = new ServingQueue1Q();
		dynamic_cast<ServingQueue1Q*>(rq)->start();
        _queues[disk] = rq;
		q = rq;
    } else {
        q = qi->second;
    }

    q->AddRequest(req);
}

bool DiskQueues::CancelRequest(RequestPtr &req, DiskId disk) {
    if (_queues.find(disk) != _queues.end())
        return _queues[disk]->CancelRequest(req);
    else
        return false;
}

RequestQueue* DiskQueues::GetQueue(DiskId disk) {
    if (_queues.find(disk) != _queues.end())
        return _queues[disk];
    else
        return NULL;
}

void DiskQueues::SetPriorityOp(RequestQueue::PriorityOp op) 
{
      RequestQueueMap::iterator it = _queues.begin();
  		while(it != _queues.end()) {
        it->second->SetPriorityOp(op);
   	}
}

} 

